package qc.module.demo.api.controller;

import com.rtdb.api.model.RtdbData;
import com.rtdb.enums.RtdbHisMode;
import com.rtdb.model.*;
import com.rtdb.service.impl.BaseImpl;
import com.rtdb.service.impl.HistorianImpl;
import com.rtdb.service.impl.ServerImpl;
import com.rtdb.service.inter.Base;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import qc.common.core.utils.DateUtil;
import qc.module.demo.dto.powerplant.HydrogenLeakageDynamoStatisticsResultDto;
import qc.module.demo.dto.powerplant.HydrogenLeakageStatisticsConditionDto;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 阳宗海电厂相关接口
 *
 * @author QuCheng Tech
 * @since 2025/11/21
 */
@RestController
@RequestMapping("/yzh")
public class YzhController {
    /**
     * 获取指定点号的信息
     *
     * @param id 传入的可以是点号id或tagname
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/sispoint", method = {RequestMethod.GET})
    public String getSisPointPropertyByParam(@RequestParam(value = "id", required = true) String id) {
        return getSisPointsProperty(id);
    }

    /**
     * 获取指定点号的信息
     *
     * @param id 传入的可以是点号id或tagname
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/sispoint/{id}", method = {RequestMethod.GET})
    public String getSisPointPropertyByPath(@PathVariable(value = "id", required = true) String id) {
        return getSisPointsProperty(id);
    }

    /**
     * 获取指定点号的信息
     *
     * @param id 传入的可以是点号id或tagname
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    String getSisPointsProperty(String id) {
        if (StringUtils.isBlank(id))
            return "传入的点号Id或tag不能为空";
        try {
            //获取单个数据库连接
            ServerImpl server = new ServerImpl("10.113.96.14", 6327, "sa", "VeStore-123#!");
            Base base = new BaseImpl(server);
            try {
                int pointid = Integer.parseInt(id);
                //根据点号ID获取点号信息
                Entity<FullPoint> points = base.getPointsProperties(new int[]{pointid});
                if (points != null && points.getSucCount() > 0x0) {
                    FullPoint point = points.getList().get(0x0);
                    BasePoint basePoint = point.getBasePoint();

                    return "tag:" + basePoint.getTag() + "\r\n" + "id:" + basePoint.getId();
                }
            } catch (NumberFormatException ex) {
                //传入的是tagname，根据tagname获取点号信息
                Entity<MinPoint> points = base.getPointsProperties(new String[]{id});
                if (points != null && points.getSucCount() > 0x0) {
                    MinPoint point = points.getList().get(0x0);

                    return "tag:" + point.getTagName() + "\r\n" + "id:" + point.getId();
                }
            } finally {
                base.close();
                server.close();
            }
        } catch (Exception ex) {
            return ex.getMessage();
        }

        return null;
    }

    /**
     * 获取指定一个时间点的数据；
     * 指定1个点号；时间点传入错误或为空时默认使用当前时间；取数模式默认为2-指定时间点，如果没有保持为空；
     * url示例：http://server/demo/yzhsis/point?ids=xxx&tm=xxx&mode=2
     * 调用HistorianImpl中的getCrossSectionValues方法。
     *
     * @param id   点号ID
     * @param tm   时间，为空时默认为当前时间
     * @param mode 取数模式；0-下一个最近，1-上一个最近，2-指定时间点，3-内插值；
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/sistime", method = {RequestMethod.GET})
    public String getSisTimeData(@RequestParam(value = "id", required = true) int id,
                                 @RequestParam(value = "tm", required = false) String tm,
                                 @RequestParam(value = "mode", required = false) int mode) {
        //时间点初始为当前时间
        Date dateTime = DateUtil.getNowDate();
        //取数模式；0-下一个最近，1-上一个最近，2-指定时间点，3-内插值；初始为2
        RtdbHisMode modeEnum = RtdbHisMode.RTDB_EXACT;
        if (StringUtils.isNotBlank(tm)) {
            Date time = DateUtil.parseDate(tm);
            if (time != null)
                dateTime = time;
        }
        if (mode == 0x0)
            modeEnum = RtdbHisMode.RTDB_NEXT;
        else if (mode == 0x1)
            modeEnum = RtdbHisMode.RTDB_PREVIOUS;
        else if (mode == 0x2)
            modeEnum = RtdbHisMode.RTDB_EXACT;
        else if (mode == 0x3)
            modeEnum = RtdbHisMode.RTDB_INTER;

        try {
            //获取单个数据库连接
            ServerImpl server = new ServerImpl("10.113.96.14", 6327, "sa", "VeStore-123#!");
            //历史查询服务实现类
            HistorianImpl historian = new HistorianImpl(server);

            List<RtdbData> dbDatas = historian.getCrossSectionValues(new int[]{id}, dateTime, modeEnum);
            if (dbDatas != null && dbDatas.size() > 0x0) {
                StringBuilder sb = new StringBuilder();
                for (RtdbData data : dbDatas) {
                    int dataId = data.getId();
                    Double dataValue = (Double) data.getValue();
                    Date dataTime = data.getDate();

                    sb.append("id:" + dataId + "\t tm:" + DateUtil.getDateTimeString(dataTime) + "\t value:" + dataValue + "\r\n");
                }

                return sb.toString();
            } else {
                return "未查询到任何数据";
            }
        } catch (Exception ex) {
            return ex.getMessage();
        }
    }

    /**
     * 获取指定时间段内的点号数据集合；
     * 指定1个点号；时间点传入错误或为空时默认使用当前时间；
     * url示例：http://server/demo/yzhsis/range?ids=xxx&tm=xxx&mode=2
     * 调用HistorianImpl中的getArchivedValues方法。
     *
     * @param id  点号ID
     * @param btm 时间，为空时默认为当天0点
     * @param etm 时间，为空时默认为当前时间
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/sisrange", method = {RequestMethod.GET})
    public String getSisArchivedValues(@RequestParam(value = "id", required = true) int id,
                                       @RequestParam(value = "btm", required = false) String btm,
                                       @RequestParam(value = "etm", required = false) String etm) {
        //时间段初始为当天0点值当前时间
        Date beginTime = DateUtil.getTodayDate();
        Date endTime = DateUtil.getNowDate();
        if (StringUtils.isNotBlank(btm)) {
            Date time = DateUtil.parseDate(btm);
            if (time != null)
                beginTime = time;
        }
        if (StringUtils.isNotBlank(etm)) {
            Date time = DateUtil.parseDate(etm);
            if (time != null)
                endTime = time;
        }

        try {
            //获取单个数据库连接
            ServerImpl server = new ServerImpl("10.113.96.14", 6327, "sa", "VeStore-123#!");
            //历史查询服务实现类
            HistorianImpl historian = new HistorianImpl(server);

            //默认查询时间段的最大数据条数为10万条
            List<RtdbData> dbDatas = historian.getArchivedValues(id, 100000, beginTime, endTime);
            if (dbDatas != null && dbDatas.size() > 0x0) {
                StringBuilder sb = new StringBuilder();
                for (RtdbData data : dbDatas) {
                    int dataId = data.getId();
                    Double dataValue = (Double) data.getValue();
                    Date dataTime = data.getDate();

                    sb.append("id:" + dataId + "\t tm:" + DateUtil.getDateTimeString(dataTime) + "\t value:" + dataValue + "\r\n");
                }

                return sb.toString();
            } else {
                return "未查询到任何数据";
            }
        } catch (Exception ex) {
            return ex.getMessage();
        }
    }

    /**
     * 获取指定时间段内的点号数据的累计值；如获取年累计电量
     * 指定1个点号；时间点传入错误或为空时默认使用当前时间；
     * url示例：http://server/demo/yzhsis/sum?ids=xxx&tm=xxx&mode=2
     * 调用HistorianImpl中的getNumberSummary方法。
     *
     * @param id  点号ID
     * @param btm 时间，为空时默认为当天0点
     * @param etm 时间，为空时默认为当前时间
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/sissum", method = {RequestMethod.GET})
    public String getSisNumberSummary(@RequestParam(value = "id", required = true) int id,
                                      @RequestParam(value = "btm", required = false) String btm,
                                      @RequestParam(value = "etm", required = false) String etm) {
        //时间段初始为当天0点值当前时间
        Date beginTime = DateUtil.getTodayDate();
        Date endTime = DateUtil.getNowDate();
        if (StringUtils.isNotBlank(btm)) {
            Date time = DateUtil.parseDate(btm);
            if (time != null)
                beginTime = time;
        }
        if (StringUtils.isNotBlank(etm)) {
            Date time = DateUtil.parseDate(etm);
            if (time != null)
                endTime = time;
        }

        try {
            //获取单个数据库连接
            ServerImpl server = new ServerImpl("10.113.96.14", 6327, "sa", "VeStore-123#!");
            //历史查询服务实现类
            HistorianImpl historian = new HistorianImpl(server);

            //默认查询时间段的最大数据条数为10万条
            SummaryEntity summaryEntity = historian.getNumberSummary(id, beginTime, endTime);
            if (summaryEntity != null) {
                StringBuilder sb = new StringBuilder();
                sb.append("数据条数:" + summaryEntity.getCount() + "\r\n");
                sb.append("合计值:" + summaryEntity.getTotalValue() + "\r\n");
                sb.append("平均值:" + summaryEntity.getCalcAvg() + "\r\n");
                sb.append("最小值:" + summaryEntity.getMinValue() + "\r\n");
                sb.append("最小值时间:" + DateUtil.getDateTimeString(summaryEntity.getMinValueTime()) + "\r\n");
                sb.append("最大值:" + summaryEntity.getMaxValue() + "\r\n");
                sb.append("最大值时间:" + DateUtil.getDateTimeString(summaryEntity.getMaxValueTime()) + "\r\n");

                return sb.toString();
            } else {
                return "未查询到任何数据";
            }
        } catch (Exception ex) {
            return ex.getMessage();
        }
    }

    /**
     * 漏氢率统计
     *
     * @param condition 统计条件
     * @return qc.module.demo.dto.powerplant.HydrogenLeakageStatisticsResultDto
     * @author QuCheng Tech
     * @since 2025/11/21
     */
    @RequestMapping(value = "/hydrogen", method = {RequestMethod.GET, RequestMethod.POST})
    public HydrogenLeakageDynamoStatisticsResultDto statisticsHydrogenLeakage(@RequestBody HydrogenLeakageStatisticsConditionDto condition) {
        //初始化返回结果，设置统计成功标记为false
        HydrogenLeakageDynamoStatisticsResultDto result = new HydrogenLeakageDynamoStatisticsResultDto();
        result.setSuccess(false);

        //验证输入的统计条件是否正确
        if (condition == null) {
            result.setMsg("统计条件不能为空");
            return result;
        }
        if (StringUtils.isBlank(condition.getBegintm())) {
            result.setMsg("统计的开始时间不能为空");
            return result;
        }
        if (StringUtils.isBlank(condition.getEndtm())) {
            result.setMsg("统计的截止时间不能为空");
            return result;
        }
        Date beginTime = DateUtil.parseDate(condition.getBegintm());
        if (beginTime == null) {
            result.setMsg("统计的开始时间错误，无法转换为有效的时间");
            return result;
        }
        Date endTime = DateUtil.parseDate(condition.getEndtm());
        if (endTime == null) {
            result.setMsg("统计的截止时间错误，无法转换为有效的时间");
            return result;
        }
        if (endTime.after(beginTime) == false) {
            result.setMsg("统计的开始时间不能大于截止时间");
            return result;
        }
        //机组顺序，取值为3、4分别表示3#、4#机组，默认为3#机组
        int dynamoNo = 0x3;
        if (condition.getDynamo() == 0x4)
            dynamoNo = 0x4;

        //静态常量数值
        double capacity = 72;//发电机容积m3
        double airPressure = 0.0825;//当地绝对压力Mpa
        double const_value1 = 293;//数值含义不清楚，有可能是装机容量和平均负荷
        double const_value2 = 273;//数值含义不清楚

        //double hours = 24;//统计时间跨度小时数
        //计算时间跨度小时数
        double hours = DateUtil.getDistanceHours(beginTime, endTime);

        //计算输入或中间过程数值定义及初始化，先初始化对应数值为NaN用于判断是否有取到对应的数值
        double beginPressureValue = Double.NaN;//补氢前压力值
        Date beginPressureTime = null;
        double endPressureValue = Double.NaN;//补氢后压力值
        Date endPressureTime = null;
        Map<String, Double> beginTemps = new LinkedHashMap<>();
        Map<String, Double> endTemps = new LinkedHashMap<>();
        double beginAvgTemp = Double.NaN;//补氢前平均温度，为几个点号平均值的平均
        double endAvgTemp = Double.NaN;//补氢后平均温度，为几个点号平均值的平均
        double avgMw = Double.NaN;//平均负荷

        boolean getDataFromSis = false;//开发测试时设置为false，正式使用设置为true
        if (getDataFromSis == true) {
            //从sis提取输入数据和计算中间数值
            try {
                //获取单个数据库连接
                ServerImpl server = new ServerImpl("10.113.96.14", 6327, "sa", "VeStore-123#!");
                //历史查询服务实现类
                HistorianImpl historian = new HistorianImpl(server);

                //取对应时间点的氢压力、温度(多个点号值)
                //取数模式；0-下一个最近，1-上一个最近，2-指定时间点，3-内插值；初始为3
                RtdbHisMode hisMode = RtdbHisMode.RTDB_INTER;
                //3#机组点号：压力-DCS3.PT5002、温度-DCS3.TE129	DCS3.TE130	DCS3.TE131	DCS3.TE132	DCS3.TE133	DCS3.TE134	DCS3.TE135	DCS3.TE136
                //4#机组点号：压力-DCS4.PT5002、温度-DCS4.TE129	DCS4.TE130	DCS4.TE131	DCS4.TE132	DCS4.TE133	DCS4.TE134	DCS4.TE135	DCS4.TE136
                int[] ids = new int[]{0x1};
                if (dynamoNo == 0x4)
                    ids = new int[]{0x1};

                //查询起始时间点数据
                try {
                    List<RtdbData> beginTimeDatas = historian.getCrossSectionValues(ids, beginTime, hisMode);
                    if (beginTimeDatas != null && beginTimeDatas.size() > 0x0) {
                        for (RtdbData data : beginTimeDatas) {
                            int dataId = data.getId();
                            Double dataValue = (Double) data.getValue();
                            Date dataTime = data.getDate();

                            if (dataId == 0x0) {
                                //压力
                                beginPressureValue = dataValue;
                                beginPressureTime = dataTime;
                            } else {
                                //温度
                                beginTemps.put(String.valueOf(dataId), dataValue);
                            }
                        }
                    } else {
                    }
                } catch (Exception ex) {
                    result.setMsg("从SIS查询起始时间点数据值时异常，" + ex.getMessage());
                }

                //查询截止时间点数据
                try {
                    List<RtdbData> endTimeDatas = historian.getCrossSectionValues(ids, endTime, hisMode);
                    if (endTimeDatas != null && endTimeDatas.size() > 0x0) {
                        for (RtdbData data : endTimeDatas) {
                            int dataId = data.getId();
                            Double dataValue = (Double) data.getValue();
                            Date dataTime = data.getDate();

                            if (dataId == 0x0) {
                                //压力
                                endPressureValue = dataValue;
                                endPressureTime = dataTime;
                            } else {
                                //温度
                                endTemps.put(String.valueOf(dataId), dataValue);
                            }
                        }
                    } else {
                    }
                } catch (Exception ex) {
                    result.setMsg("从SIS查询截止时间点数据值时异常，" + ex.getMessage());
                }

                //取时间段内的平均负荷值--目前不参与计算
                //负荷点号
                final int dynamo1MwId = 63479;//3#机组负荷-DCS3.13B51AI011
                final int dynamo2MwId = 66030;//4#机组负荷-DCS4.13B51AI011
                try {
                    SummaryEntity summaryEntity = historian.getNumberSummary(dynamoNo == 0x3 ? dynamo1MwId : dynamo2MwId, beginTime, endTime);
                    if (summaryEntity != null) {
                        double totalValue = summaryEntity.getTotalValue();//累计值
                        double calcAvg = summaryEntity.getCalcAvg();//算术平均值
                        double powerAvg = summaryEntity.getPowerAvg();//加权平均值，时间加权

                        avgMw = powerAvg;
                    }
                } catch (Exception ex) {
                    //负荷暂时不参与计算，查询sis接口异常时不返回错误
                    //result.setMsg("从SIS查询平均负荷时异常，" + ex.getMessage());
                }
            } catch (Exception ex) {
                result.setMsg("调用SIS接口时异常，" + ex.getMessage());
            }
        }

        //测试或调试时手动赋值
        hours = 24;//统计时间跨度小时数
        beginPressureValue = 0.2522;//补氢前压力值
        endPressureValue = 0.25183;//补氢后压力值
        //beginAvgTemp = 0.0;//补氢前平均温度，为几个点号平均值的平均
        //endAvgTemp = 0.0;//补氢后平均温度，为几个点号平均值的平均
        beginTemps.put("test1", 333.0);
        beginTemps.put("test2", 345.0);
        endTemps.put("test1", 334.0);
        endTemps.put("test2", 348.0);
        beginPressureTime = beginTime;
        endPressureTime = endTime;

        //如果返回结果中的msg不为空，表示在调用sis接口时异常，返回结果
        if (StringUtils.isNotBlank(result.getMsg()))
            return result;
        //基本判断，如果没有对应的计算输入值无法进行计算
        if (Double.isNaN(beginPressureValue)) {
            result.setMsg("开始时间点的压力数值缺失，无法进行统计。");
            return result;
        }
        if (Double.isNaN(endPressureValue)) {
            result.setMsg("截止时间点的压力数值缺失，无法进行统计。");
            return result;
        }
        if (beginTemps.size() < 0x1) {
            result.setMsg("开始时间点的时机内温度数值缺失，无法进行统计。");
            return result;
        }
        if (endTemps.size() < 0x1) {
            result.setMsg("截止时间点的时机内温度数值缺失，无法进行统计。");
            return result;
        }
        //计算平均温度
        double sumTemp = 0.0;
        for (Map.Entry<String, Double> entry : beginTemps.entrySet()) {
            sumTemp += entry.getValue();
        }
        beginAvgTemp = sumTemp / beginTemps.size();
        sumTemp = 0.0;
        for (Map.Entry<String, Double> entry : endTemps.entrySet()) {
            sumTemp += entry.getValue();
        }
        endAvgTemp = sumTemp / endTemps.size();

        //漏氢率计算公式：A5*(293/0.1)*(24/H5)*(((F4+B5)/(273+G4))-((E5+B5)/(273+G5)))
        double diff = (beginPressureValue + airPressure) / (const_value2 + beginAvgTemp) - (endPressureValue + airPressure) / (const_value2 + endAvgTemp);
        double rate = capacity * (const_value1 / 0.1) * (24 / hours) * diff;

        //返回结果赋值
        result.setDynamoName(dynamoNo == 0x3 ? "#3机" : "#4机");
        result.setBegintm(DateUtil.getDateTimeString(beginTime));
        result.setEndtm(DateUtil.getDateTimeString(endTime));
        result.setSuccess(true);
        result.setHours(hours);
        result.setRate(rate);
        result.setCapacity(capacity);
        result.setAirPressure(airPressure);
        result.setBeginPressureValue(beginPressureValue);
        result.setBeginPressureTime(DateUtil.getDateTimeString(beginPressureTime));
        result.setEndPressureValue(endPressureValue);
        result.setEndPressureTime(DateUtil.getDateTimeString(endPressureTime));
        result.setBeginAvgTemp(beginAvgTemp);
        result.setBeginTemps(beginTemps);
        result.setEndAvgTemp(endAvgTemp);
        result.setEndTemps(endTemps);
        result.setAvgMw(avgMw);

        return result;
    }
}
